home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mush-7.1.1 / init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-02  |  13.1 KB  |  458 lines

  1. /* init.c    (c) copyright 1986 (Dan Heller) */
  2.  
  3. /* init.c -- functions and whatnot that initialize everything */
  4. #include "mush.h"
  5. #include <pwd.h>
  6.  
  7. #ifdef BSD
  8. #include <netdb.h>
  9. #endif /* BSD */
  10.  
  11. #ifdef SYSV
  12. #include <sys/utsname.h>
  13. #endif /* SYSV */
  14.  
  15. void
  16. init()
  17. {
  18.     char         *home, *realname, *argv[4];
  19.     extern char        *getlogin();
  20.     char        buf[MAXPATHLEN];
  21. #ifdef SYSV
  22.     extern struct passwd *getpwuid();  /* sys-v forgot this in pwd.h! */
  23.     struct utsname ourhost;
  24. #else
  25.     char ourhost[128];
  26. #endif /* SYSV */
  27.     register char     *p;
  28.     struct passwd     *entry;
  29.     int            cnt;
  30. #ifdef BSD
  31.     struct hostent     *hp;
  32. #endif /* BSD */
  33.  
  34.     home = getenv("HOME");
  35.     if (realname = getenv("NAME")) {
  36.     (void) strcpy(buf, realname);
  37.     }
  38.     argv[1] = "=";
  39.     argv[3] = NULL;
  40.  
  41.     if (!(entry = getpwuid(getuid())))
  42.     if (p = getlogin())
  43.         strdup(login, p);
  44.     else {
  45.         login = "unknown";
  46.         print("I don't know you, but that's ok.\n");
  47.     }
  48.     else {
  49.     strdup(login, entry->pw_name);
  50.     if (!home || !*home)
  51.         home = entry->pw_dir;
  52.     if (!realname && (realname = entry->pw_gecos)) {
  53.         if (p = index(realname, ','))
  54.         *p = 0;
  55.         for (p = buf; *realname; realname++)
  56.         if (*realname == '&')
  57.             *p++ = upper(*login), p += Strcpy(p, login+1);
  58.         else
  59.             *p++ = *realname;
  60.         *p = 0;
  61.     }
  62.     endpwent();
  63.     }
  64.     if (!home || !*home || Access(home, W_OK)) {
  65.     if (home && *home)
  66.         error(home);
  67.     else
  68.         print("No home!? ");
  69.     print_more("Using \"%s\" as home.\n", ALTERNATE_HOME);
  70.     } else {
  71.     argv[0] = "home";
  72.     argv[2] = home;
  73.     (void) add_option(&set_options, argv);
  74.     }
  75.     if (realname) {
  76.     /* realname has already been copied to buf */
  77.     argv[0] = "realname";
  78.     argv[2] = buf;
  79.     (void) add_option(&set_options, argv);
  80.     }
  81.     crt = 24;
  82.     screen = 18;
  83.     wrapcolumn = 0; /* Default is no wrap */
  84.     escape = DEF_ESCAPE;
  85.     prompt = DEF_PROMPT;
  86.  
  87. #ifdef BSD
  88.     (void) gethostname(ourhost, sizeof ourhost);
  89.     if (!(hp = gethostbyname(ourhost))) {
  90.     error("gethostbyname: %s", ourhost);
  91.     if (ourname = (char **)calloc((unsigned)2, sizeof (char *)))
  92.         strdup(ourname[0], ourhost);
  93.     } else {
  94.     int n = 0;
  95.     cnt = 2; /* 1 for ourhost and 1 for NULL terminator */
  96.     for (p = hp->h_name; p && *p; p = hp->h_aliases[n++])
  97.         if (strcmp(ourhost, p)) /* if host name is different */
  98.         cnt++;
  99.     if (ourname = (char **)calloc((unsigned)cnt, sizeof (char *))) {
  100.         ourname[--cnt] = NULL;
  101.         for (p = hp->h_name; p && *p && n >= 0; p = hp->h_aliases[--n])
  102.         if (strcmp(ourhost, p)) /* if host name is different */
  103.             ourname[--cnt] = savestr(p);
  104.         strdup(ourname[0], ourhost); /* cnt better be 0! */
  105.     }
  106.     }
  107. #endif /* BSD */
  108. #ifdef SYSV
  109.     if (ourname = (char **)calloc((unsigned)2, sizeof (char *))) {
  110.     if ((uname (&ourhost) >= 0) && (*ourhost.nodename))
  111.         ourname[0] = savestr(ourhost.nodename);
  112.     else {
  113.         /* Try to use uuname -l to get host's name if uname didn't work */
  114.         char buff[50];
  115.         char *p;
  116.         FILE *F;
  117.  
  118.         if (F = popen("exec uuname -l", "r")) {
  119.         if ((fgets(buff, sizeof buff, F) == buff) &&
  120.             (p = strchr(buff, '\n'))) {
  121.             *p = '\0';        /* eliminate newline */
  122.             ourname[0] = savestr (buff);
  123.         }
  124.         (void)pclose(F);
  125.         }
  126.     }
  127.     }
  128. #endif /* SYSV */
  129.     if (ourname && ourname[0]) {
  130.     for (p = buf, cnt = 0; ourname[cnt]; cnt++) {
  131.         if (cnt)
  132.         *p++ = ' ';
  133.         p += Strcpy(p, ourname[cnt]);
  134.     }
  135.     argv[0] = "hostname";
  136.     argv[2] = buf;
  137.     (void) add_option(&set_options, argv);
  138.     }
  139.  
  140.     init_bindings();
  141. }
  142.  
  143. /*
  144.  * Source a file, or just the default file.  Since sourcing files
  145.  * means reading possible aliases, don't expand the ! as history
  146.  * by setting the IGN_BANG flag.  Since a command in the sourced file
  147.  * may call source on another file, this routine may be called from
  148.  * within itself.  Continue to ignore ! chars by setting save_bang (local).
  149.  *
  150.  * Try opening the file passed to us.  If not given, check for the correct
  151.  * .rc file which is found in the user's home dir.
  152.  *
  153.  * return -1 for filesystem errors, -2 for attempting to read a directory.
  154.  */
  155. source(argc, argv)
  156. char **argv;
  157. {
  158.     register char *p;
  159.     FILE      *fp;
  160.     char       file[MAXPATHLEN];
  161.     u_long      save_bang = ison(glob_flags, IGN_BANG);
  162.     int          line_no = 0;
  163.  
  164.     if (argc && *++argv && !strcmp(*argv, "-?"))
  165.     return help(0, "source", cmd_help);
  166.     if (argc && *argv)
  167.     (void) strcpy(file, *argv);
  168.     else if ((p = getenv("MUSHRC")) && *p || (p = getenv("MAILRC")) && *p)
  169.     (void) strcpy(file, p);
  170.     else {
  171.     char *home = do_set(set_options, "home");
  172.     if (!home || !*home)
  173.         home = ALTERNATE_HOME;
  174.     if (Access(sprintf(file, "%s/%s", home, MAILRC), R_OK)
  175.         && Access(sprintf(file, "%s/%s", home, ALTERNATE_RC), R_OK))
  176.         if (argc || argv)
  177.         (void) strcpy(file, DEFAULT_RC);
  178.         else
  179.         return -1;
  180.     }
  181.  
  182.     argc = 0; /* don't ignore ENOENT */
  183.     p = getpath(file, &argc);
  184.     /* Try the ALT_DEF_RC if DEFAULT_RC fails */
  185.     if (argc && !strcmp(file, DEFAULT_RC)) {
  186.     argc = 0; /* don't ignore ENOENT */
  187.     (void) strcpy(file, ALT_DEF_RC);
  188.     p = getpath(file, &argc);
  189.     }
  190.     if (argc) {
  191.     /* Don't print error messages for missing default files */
  192.     if (strcmp(file, ALT_DEF_RC))
  193.         if (argc == -1) {
  194.         print("%s: %s\n", file, p);
  195.         return -1;
  196.         } else {
  197.         print("%s is a directory.\n", file);
  198.         return -2;
  199.         }
  200.     return -1;
  201.     }
  202.     if (!(fp = fopen(p, "r"))) {
  203.     if (errno != ENOENT)
  204.         error("Can't open %s", p);
  205.     return -1;
  206.     }
  207.     turnon(glob_flags, IGN_BANG); /* ignore ! when reading record files */
  208.     (void) strcpy(file, p);
  209.     (void) src_parse(file, fp, 0, 0, &line_no);
  210.     /* if we entered the routine ignoring !, leave it that way. */
  211.     if (!save_bang)
  212.     turnoff(glob_flags, IGN_BANG);
  213.     /* Sourcing might change things, so abort pipes/macros */
  214.     return 0 - (in_pipe() || in_macro());
  215. }
  216.  
  217. /*
  218.  * Do the actual file parsing for source().  The first argument should
  219.  * be the name of the file referenced by the second argument.  The third
  220.  * argument is used for handling nested if_else_endif expressions.  The
  221.  * fourth argument is used to keep track of the recursion depth, and the
  222.  * last argument keeps track of the line number in the current file.
  223.  *
  224.  * This function calls itself recursively.  It also calls do_command(),
  225.  * which may in turn call source() recursively.
  226.  *
  227.  * If-then-else nesting algorithm:
  228.  *  On any "if" (whether parsing or not), increment if_else
  229.  *  On true "if" when parsing, evaluate by recursion
  230.  *  On false "if" when parsing, set find_else equal to if_else
  231.  *  On any "if" when not parsing, set find_endif equal to if_else
  232.  *  On "else", invert parsing only when find_else equals if_else
  233.  *  When "if" was false and there is nesting, recur for "else"
  234.  *  Skip nested "if...endif" when find_else or find_endif true
  235.  *  On "endif" or when recursion returns, decrement if_else
  236.  *  On "endif", test both find_endif and find_else against if_else:
  237.  *   when either matches, reset that one;
  238.  *   when the lesser (less nested) matches, resume parsing
  239.  *  On "endif", when if_else hits 0, continue (depth 0) or return
  240.  */
  241. src_parse(file, fp, if_else, depth, line_no)
  242. char    *file;
  243. FILE    *fp;
  244. int      if_else, depth, *line_no;
  245. {
  246.     register char *p, *p2, **newargv;
  247.     static int    exited;
  248.     int       parsing = 1, cont_line = 0;
  249.     int          find_else = 0, find_endif = 0;
  250.     char       line[BUFSIZ];
  251.     int          argc;
  252.  
  253.     exited = 0;
  254.  
  255.     while (p = fgets(&line[cont_line], BUFSIZ - cont_line, fp)) {
  256.     (*line_no)++;
  257.     if (*(p2 = no_newln(p)) == '\\') {
  258.         *p2++ = ' ';
  259.         cont_line = p2 - line;
  260.         continue;
  261.     } else
  262.         cont_line = 0;
  263.     /* don't consider comments (#) in lines. check if # is within quotes */
  264.     if (p = any(line, "\"'#\\")) {
  265.         register int balanced = 1;
  266.         do {
  267.         if (*p == '\\' && p[1])
  268.             p = any(p+2, "\"'#\\");
  269.         else if (*p != '#') {
  270.             /* first find matching quote */
  271.             register char *quote = index(p+1, *p);
  272.             if (!quote) {
  273.             print("%s: line %d: unbalanced %c.\n",
  274.                 file, *line_no, *p);
  275.             balanced = 0;
  276.             } else
  277.             p = any(quote+1, "\"'#\\");
  278.         }
  279.         } while (p && *p != '#' && balanced);
  280.         if (!balanced)
  281.         continue;
  282.         if (p && *p == '#')
  283.         *p = 0; /* found a Comment: null terminate line at comment */
  284.     }
  285.     if (!*line || !parsing && !(newargv = mk_argv(line, &argc, 0))
  286.     || parsing && !(newargv = make_command(line, TRPL_NULL, &argc))) {
  287.         if (!strncmp(line, "if", 2))
  288.         find_else = ++if_else, parsing = FALSE;
  289.         continue;
  290.     }
  291.     if (!strcmp(newargv[0], "endif")) {
  292.         if (!if_else)
  293.         print("%s: line %d: endif with no \"if\".\n", file, *line_no);
  294.         else {
  295.         /* If looking for an else or endif, reset parsing */
  296.         if (find_endif && find_endif == if_else) {
  297.             if (find_endif <= find_else || !find_else)
  298.             parsing = 1, find_else = 0;
  299.             find_endif = 0;
  300.         }
  301.         /* Note: find_else never < find_endif */
  302.         if (find_else && find_else == if_else)
  303.             parsing = !parsing, find_else = 0;
  304.         /* Decrement if_else and check depth */
  305.         if (--if_else == 0)
  306.             /* Resume parsing if at the top */
  307.             if (depth == 0)
  308.             parsing = 1;
  309.             /* Return if not at the top */
  310.             else
  311.             return 1;
  312.         }
  313.         goto bad;
  314.     } else if (!strcmp(newargv[0], "else")) {
  315.         if (!if_else)
  316.         print("%s: line %d: if-less \"else\".\n", file, *line_no);
  317.         /* If inside an else, ignore nested else;
  318.          *  otherwise, recur when if_else > 1 */
  319.         else if (!find_else && !find_endif && !parsing) {
  320.         parsing = src_parse(file, fp, 1, depth + 1, line_no);
  321.         --if_else;
  322.         } else if (find_else == if_else || if_else == 1) {
  323.         find_else = 0;
  324.         parsing = !parsing;
  325.         if (!parsing)
  326.             find_endif = if_else;
  327.         }
  328.         goto bad;
  329.     } else if (!strcmp(newargv[0], "if")) {
  330.         /* if statements are of the form:
  331.          *     if expr
  332.          *     if !expr  or  if ! expr
  333.          *     if expr == expr   or   if expr != expr
  334.          */
  335.         int equals = TRUE, pattern = FALSE;
  336.         register char *lhs = newargv[1], *rhs = NULL;
  337.  
  338.         if_else++;
  339.         /* If parsing, set parsing to 0 until
  340.          *  evaluating the "if" proves otherwise.
  341.          * If not parsing, skip to the "endif".
  342.          */
  343.         if (parsing)
  344.         parsing = 0;
  345.         else {
  346.         if (!find_endif)
  347.             find_endif = if_else;
  348.         goto bad;
  349.         }
  350.         if (!lhs || !*lhs) {
  351.         print("%s: line %d: if what?\n", file, *line_no);
  352.         goto bad;
  353.         }
  354.         /* "lhs" is the left hand side of the equation
  355.          * In this instance, we're doing case 2 above (check for negation).
  356.          */
  357.         if (*lhs == '!') {
  358.         if (!*++lhs && !(lhs = newargv[2])) {
  359.             print("%s: line %d: syntax error: \"if ! <what?>\"\n",
  360.             file, *line_no);
  361.             goto bad;
  362.         }
  363.         equals = FALSE;
  364.         }
  365.         if (*lhs == '-' && (lhs[1] == 'e' || lhs[1] == 'z') && !lhs[2]) {
  366.         char *path;
  367.         int n = 1; /* ignore ENOENT, I'll handle it here */
  368.         struct stat statb;
  369.  
  370.         /* check for existence or zero-length folders/files */
  371.         if (argc > 3 + (!equals)) {
  372.             print("%s: line %d: if %s \"filename\"\n",
  373.             file, *line_no, lhs);
  374.             goto bad;
  375.         }
  376.         path = getpath(newargv[argc-1], &n);
  377.         parsing = !equals ^ (n == -1 || n == 1 && lhs[1] == 'e' ||
  378.             !stat(path, &statb) && (lhs[1] == 'e' || !statb.st_size));
  379.         } else {
  380.         if (equals && argc > 2) {
  381.             if (argc != 4) {
  382.             print("%s: %d: argument count error: %d args.\n",
  383.                 file, *line_no, argc);
  384.             goto bad;
  385.             }
  386.             /* now check newargv[2] for == or != or =~ or !~ */
  387.             if (!strcmp(newargv[2], "!=") ||
  388.                 (pattern = !strcmp(newargv[2], "!~")))
  389.             equals = !equals;
  390.             else if (!strcmp(newargv[2], "=~"))
  391.             pattern = TRUE;
  392.             else if (strcmp(newargv[2], "==")) {
  393.             print("%s: %d: use `==' or `!=' only.\n",
  394.                 file, *line_no);
  395.             goto bad;
  396.             }
  397.             rhs = newargv[3];
  398.         }
  399.         if (rhs) {
  400.             /* Some fun tricks with booleans here.
  401.              * Extra ! ops make sure all == are on 0 or 1;
  402.              * aside from that, we want (glob == equals)
  403.              * or (!strcmp == equals).  Make sense?  
  404.              */
  405.             if (pattern && !glob(lhs,rhs) == !equals)
  406.             parsing = 1;
  407.             else if (!pattern && !strcmp(lhs, rhs) == !!equals)
  408.             parsing = 1;
  409.         } else if (isdigit(*lhs))
  410.             parsing = !!(atoi(lhs) ? equals : !equals);
  411.         else if (!strcmp(lhs, "redirect") && (!isatty(0) != !equals)
  412.               /* (ison(glob_flags, REDIRECT) && equals ||
  413.                isoff(glob_flags, REDIRECT) && !equals) */
  414.             || !strcmp(lhs, "is_shell") && (!is_shell == !equals)
  415.             || !strcmp(lhs, "is_sending") &&
  416.               (ison(glob_flags, IS_SENDING) && equals ||
  417.                isoff(glob_flags, IS_SENDING) && !equals)
  418.             || !strcmp(lhs, "hdrs_only") &&
  419.               (hdrs_only && equals || !hdrs_only && !equals)
  420.             || !strcmp(lhs, "istool") &&
  421.               (istool && equals || !istool && !equals)
  422.             || !strcmp(lhs, "iscurses") &&
  423.               ((iscurses || ison(glob_flags, PRE_CURSES)) && equals
  424.               || (isoff(glob_flags, PRE_CURSES) &&
  425.                   !iscurses && !equals)))
  426.             parsing = 1;
  427.         }
  428.         if (parsing) {
  429.         parsing = src_parse(file, fp, 1, depth + 1, line_no);
  430.         --if_else;
  431.         }
  432.         else
  433.         find_else = if_else; /* Look for a matching else */
  434. bad:
  435.         free_vec(newargv);
  436.         continue;
  437.     }
  438.     if (parsing && argc > 0)
  439.         if (!strcmp(newargv[0], "exit")) {
  440.         if_else = find_else = find_endif = 0;
  441.         exited = 1;
  442.         break;
  443.         } else {
  444.         (void) do_command(argc, newargv, msg_list);
  445.         exited = 0;
  446.         }
  447.     else
  448.         free_vec(newargv);
  449.     }
  450.     if (if_else && !exited)
  451.     print("%s: missing endif\n", file);
  452.     if (depth == 0)
  453.     (void) fclose(fp);
  454.     else
  455.     (void) fseek(fp, 0L, 2); /* Skip ahead to the end */
  456.     return 0;
  457. }
  458.